home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 235_02 / ovvbuf.c < prev    next >
Text File  |  1987-06-16  |  12KB  |  310 lines

  1. /* 006  13-Dec-86  ovvbuf.c
  2.  
  3.         Buffer management routines for ovview.c
  4.  
  5.         Copyright (c) 1986 by Blue Sky Software.  All rights reserved.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include "ov.h"
  11.  
  12. #define MAX_VBUF 8                     /* allow up to 8 in memory buffers */
  13. #define VBUF_LEN 16*1024               /* a buffer is 16K - make a power of 2 */
  14.  
  15. typedef struct {                       /* define the View BUFfer DEScriptior */
  16.    int buflen;
  17.    long bufoff;
  18.    char far *bufp;
  19. } VBUF_DES;
  20.  
  21. static int vidx;                       /* current VBUF descriptor in use     */
  22. static int vlast;                      /* last VBUF descriptor in use        */
  23. static int num_vbuf;                   /* highest buffer that can be alloc'd */
  24. static VBUF_DES vbufd[MAX_VBUF];       /* the arrary of VBUF descriptors     */
  25. static long bufoff;                    /* offset in file of current buffer   */
  26. static unsigned int buflen;            /* length of data in current buffer   */
  27. unsigned char far *bufp;               /* begining of data in buffer         */
  28. unsigned char far *curp;               /* current char location in buffer    */
  29. unsigned char far *endp;               /* end of current buffer              */
  30.  
  31. /*global*/  int ALTCALL vbuf_init(int );
  32. /*global*/  int ALTCALL vbuf_free(void);
  33. /*global*/  unsigned long ALTCALL vtell(void);
  34. /*global*/  int ALTCALL vseek(int ,long );
  35. /*global*/  int ALTCALL vnextch(int );
  36. /*global*/  int ALTCALL vprevch(int );
  37. static  int ALTCALL pagefwd(int ,long );
  38. static  int ALTCALL pagebck(int ,long );
  39. static  int ALTCALL vswitch(int );
  40.  
  41.  
  42. /*****************************************************************************
  43.                           V B U F _ I N I T
  44.  *****************************************************************************/
  45.  
  46. int ALTCALL
  47. vbuf_init(fh)          /* initialize the buffer system */
  48. int fh;
  49. {
  50.    vlast = -1;                         /* set indexes, etc to force an  */
  51.    num_vbuf = MAX_VBUF;                /* so the initial read loads the */
  52.    pagefwd(fh,0L);                     /* first buffer from the file    */
  53.    vswitch(0);                         /* make the 1st buffer active    */
  54.    curp = bufp;                        /* at the 1st char in 1st buffer */
  55. }
  56.  
  57.  
  58. /*****************************************************************************
  59.                           V B U F _ F R E E
  60.  *****************************************************************************/
  61.  
  62. int ALTCALL
  63. vbuf_free() {          /* release all memory buffers */
  64.  
  65.    register int i;
  66.    register VBUF_DES *vp;
  67.  
  68.    for (i = 0, vp = vbufd; i <= vlast; i++, vp++) {  /* release all buffers */
  69.       free_f(vp->bufp);
  70.       vp->bufp = NULL;
  71.    }
  72. }
  73.  
  74.  
  75. /****************************************************************************
  76.                               V T E L L
  77.  ****************************************************************************/
  78.  
  79. unsigned long ALTCALL
  80. vtell() {              /* return file offset of current character */
  81.  
  82.    return(bufoff + (curp - bufp));
  83. }
  84.  
  85.  
  86. /*****************************************************************************
  87.                                V S E E K
  88.  *****************************************************************************/
  89.  
  90. int ALTCALL
  91. vseek(fh,offset)       /* seek to specified offset in file/buffers */
  92. int fh;
  93. long offset;
  94. {
  95.    register int i;
  96.    long readoff, labs();
  97.    register VBUF_DES *vp;
  98.  
  99.    /* "seek" is easy if offset is in current buffer - normal case I hope */
  100.  
  101.    if (offset >= bufoff && offset < bufoff + VBUF_LEN) {
  102.  
  103.       curp = bufp + (offset - bufoff);
  104.       return;
  105.  
  106.    } else {    /* not in current buffer, is it in any buffer? */
  107.  
  108.       for (i = 0, vp = vbufd; i <= vlast; i++, vp++)
  109.          if (offset >= vp->bufoff && offset < vp->bufoff + VBUF_LEN) {
  110.             vswitch(i);                        /* switch to buffer with */
  111.             curp = bufp + (offset - bufoff);   /* wanted offset */
  112.             return;
  113.          }
  114.       }
  115.  
  116.    /* offset location isn't in memory, do it the old fashion way, read it */
  117.  
  118.    readoff = offset & ~((long)(VBUF_LEN-1));   /* where to read from  */
  119.  
  120.    /* special case if seeking what would be the next or prev buffer, we
  121.       keep as much buffered in memory as possible */
  122.  
  123.    if (labs(readoff - bufoff) == VBUF_LEN) {   /* reading next or prev block? */
  124.  
  125.       if (readoff > bufoff) {                  /* next block? */
  126.          pagefwd(fh,readoff);                  /* swap in next buffer */
  127.          vswitch(vidx+1);                      /* make it active */
  128.       } else {                                 /* previous block */
  129.          pagebck(fh,readoff);                  /* swap in prev buffer */
  130.          vswitch(vidx-1);                      /* make it active */
  131.       }
  132.  
  133.    } else {            /* not reading next or prev buffer */
  134.  
  135.       /* seeking to some random position in file, discard all current buffers
  136.          and start over from new position */
  137.  
  138.       vidx = vlast = 0;                        /* discard all buffers */
  139.       vbufd[0].bufoff = bufoff = readoff;      /* where to read from  */
  140.       bufp = vbufd[0].bufp;                    /* where to read to    */
  141.       l_seek(fh,readoff);
  142.       vbufd[0].buflen = buflen = readbuf(fh,bufp,VBUF_LEN);
  143.       endp = bufp + buflen;
  144.    }
  145.  
  146.   curp = bufp + (offset - bufoff);             /* got buffer, goto offset */
  147.   return;
  148. }
  149.  
  150.  
  151. /****************************************************************************
  152.                               V N E X T C H
  153.  ****************************************************************************/
  154.  
  155. int ALTCALL
  156. vnextch(fh)            /* return next character from file/buffers */
  157. int fh;
  158. {
  159.    /************** Following code is duplicated by some callers **************/
  160.  
  161.    if (curp < endp)            /* the normal case is just to return */
  162.       return(*curp++);         /*  the next character in the buffer */
  163.  
  164.    /**************************************************************************/
  165.  
  166.    if (buflen < VBUF_LEN)      /* only last buffer can be < VBUF_LEN */
  167.       return(EOF);
  168.  
  169.    if (vidx == vlast)                          /* read more from file? */
  170.       if (pagefwd(fh,bufoff+VBUF_LEN) == EOF)  /* try paging into the file */
  171.          return(EOF);                          /* watch for EOF */
  172.  
  173.    vswitch(vidx+1);                    /* switch to next buffer  */
  174.    curp = bufp;                        /* at start of buffer */
  175.  
  176.    return(*curp++);                    /* return 1st char in it */
  177. }
  178.  
  179.  
  180. /****************************************************************************
  181.                               V P R E V C H
  182.  ****************************************************************************/
  183.  
  184. int ALTCALL
  185. vprevch(fh)            /* return previous character from file/buffers */
  186. int fh;
  187. {
  188.    /************** Following code is duplicated by some callers **************/
  189.  
  190.    if (curp > bufp)            /* the normal case is just to return */
  191.       return(*--curp);         /*  the prev character in the buffer */
  192.  
  193.    /**************************************************************************/
  194.  
  195.    if (bufoff == 0)            /* at top of file? (offset == 0) */
  196.       return(EOF);
  197.  
  198.    if (vidx == 0)                      /* is this the oldest buffer? */
  199.       pagebck(fh,bufoff-VBUF_LEN);     /*   if so, page backward a buffer */
  200.  
  201.    vswitch(vidx-1);                    /* switch to prev buffer  */
  202.    curp = endp;                        /* at end of buffer */
  203.  
  204.    return(*--curp);                    /* return last char in it */
  205. }
  206.  
  207.  
  208. /*****************************************************************************
  209.                              P A G E F W D
  210.  *****************************************************************************/
  211.  
  212. static int ALTCALL
  213. pagefwd(fh,offset)     /* page forward into the file being read */
  214. int fh;
  215. long offset;
  216. {
  217.    int i;
  218.    register VBUF_DES *vp;
  219.    char far *bp, far *malloc_f();
  220.  
  221.    /* bump the index of the last buffer used, che